/**
 * \file kernel/driver.c
 * \author Davide Gessa
 * \note Gestore dei driver per hardware e altre features
 * \date 10-12-09
 */
#include <driver.h>
#include <mm/mm.h>
#include <debug.h>
#include <driver/input/keyboard.h>
#include <driver/input/mouse.h>
#include <driver/crypto/crc32.h>
#include <driver/net/rs232.h>
#include <driver/net/dp8390.h>
#include <driver/net/rtl8139.h>
#include <driver/crypto/md5.h>
#include <driver/fs/pfs/pfs.h>
#include <driver/fs/tmpfs/tmpfs.h>
#include <driver/fs/initramfs/initramfs.h>
#include <config.h>
#include <driver/bus/pci.h>
#include <driver/video/vesa.h>
#include <fs/devfs.h>
#include <video.h>

/**
 * Inizializza il gestore dei driver
 */
void driver_init()
{
	DEBUGP("driver_init()\n");
	
	device_list = NULL;
	driver_list = NULL;

	#ifdef DPCI
		driver_add(&driver_pci);
	#endif
	
	#ifdef DKEYBOARD
		driver_add(&driver_keyboard);
	#endif
	#ifdef DMOUSE
		driver_add(&driver_mouse);
	#endif
	
	
	#ifdef DMD5
		driver_add(&driver_md5);
	#endif
	#ifdef DCRC32
		driver_add(&driver_crc32);
	#endif
	
	
	#ifdef DRS232
		driver_add(&driver_rs232);
	#endif
	#ifdef DDP8390
		driver_add(&driver_dp8390);
	#endif
	#ifdef DRTL8139
		driver_add(&driver_rtl8139);
	#endif
	
	
	#ifdef DVESA
		driver_add(&driver_vesa);
	#endif
	
	
	#ifdef FSPFS
		driver_add(&driver_pfs);
	#endif
	#ifdef FSTMPFS
		driver_add(&driver_tmpfs);
	#endif
	#ifdef FSINITRAMFS
		driver_add(&driver_initramfs);
	#endif
}


/**
 * Aggiune un driver alla lista
 * 
 * \param driver puntatore al driver da aggiungere alla lista
 * \return stato dell'operazione
 */
uint32_t driver_add(driver_t *driver)
{
	//printf("%s\n",driver->name);
	driver->next = driver_list;
	driver_list = driver;
	driver->loaded = 0;
	
	return DRV_OK;
}



/**
 * Elimina un driver
 * 
 * \param n nome del driver da eliminare
 * \return stato dell'eliminazione
 */
uint32_t driver_del(char *n)
{
	driver_t *m = driver_get(n);
	driver_t *pr = driver_list;
		
	if(m == NULL) return DRV_NF_ER;
	
	
	// Cerca il precedente
	if(m == driver_list)
	{
		driver_list = NULL;
	}
	else
	{
		while(pr != NULL && pr->next != NULL)
		{
			if(strcmp(pr->next->name, n) == 0) break; 
			pr = pr->next;
		}
		pr->next = m->next;
	}	
}


/**
 * Restituisce il nome del driver dato il num
 * 
 * \param x e' il numero del driver nella lista
 * \return nome del driver nella posizione x
 */
uint32_t driver_iget(uint32_t x, driver_t **dr)
{
	int i = 0;
	driver_t *m = driver_list;
	
	while(m != NULL)
	{
		if(i == x)
		{
			*dr = m;
			return 1;
		}
		
		m = m->next;
		i++;
	}	
	*dr = NULL;
}


/**
 * Inizializza
 */
uint8_t driver_initd(char *drv)
{
	driver_t *m = driver_get(drv);
	
	if(m == NULL)
		return DRV_NF_ER;
	
	if(m->loaded == 1)
		return DRV_AL_LD;
	
	if(m->init == 0)
		return DRV_NF_IN;
	
	if(m->init() == 0)
	{
		m->loaded = 1;
		return DRV_OK;
	}
	
	return DRV_ER;
}


/**
 * Deinizializza
 */
uint8_t driver_freed(char *drv)
{
	driver_t *m = driver_get(drv);
	
	if(m == NULL)
		return DRV_NF_ER;
	
	if(m->loaded == 0)
		return DRV_NT_IN;
	
	if(m->free == 0)
		return DRV_NF_FR;
	
	if(m->free() == 0)
	{
		m->loaded = 0;
		return DRV_OK;
	}
	
	return DRV_ER;	
}


/**
 * Restituisce il driver dato il nome
 * 
 * \param name nome del driver da prelevare
 * \return il driver richiesto se e' presente, altrimenti NULL
 */
driver_t *driver_get(char *name)
{
	driver_t *m = driver_list;
	
	while(m != NULL)
	{
		if(strcmp(m->name, name) == 0)
			return m;
			
		m = m->next;	
	}
	return NULL;	
}
